home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / SOCKUSER.C < prev    next >
C/C++ Source or Header  |  1993-10-03  |  10KB  |  542 lines

  1. #include "global.h"
  2. #include "config.h"
  3. #ifdef    ANSIPROTO
  4. #include <stdarg.h>
  5. #endif
  6. #include <conio.h>
  7. #include "mbuf.h"
  8. #include "proc.h"
  9. #include "socket.h"
  10. #ifdef LZW
  11. #include "lzw.h"
  12. #endif
  13. #include "usock.h"
  14. #include "session.h"
  15. #include "nr4.h"
  16.  
  17. #ifndef EOF
  18. #define EOF (EOF)
  19. #endif
  20.  
  21. #ifdef SOBUF
  22. #undef SOBUF
  23. #endif
  24.  
  25. #define    SOBUF    768
  26.  
  27. static int near usvprintf __ARGS((int s,char *fmt, va_list args));
  28.  
  29. #ifdef XXX
  30. static int near
  31. strlen(char *s)
  32. {
  33.     int i = 0;
  34.  
  35.     while(*s++ != '\0')
  36.         i++;
  37.     return i;
  38. }
  39. #endif
  40.  
  41. #ifdef XXX
  42. /* Higher-level receive routine, intended for connection-oriented sockets.
  43.  * Can be used with datagram sockets, although the sender id is lost.
  44.  */
  45. int
  46. recv(s,buf,len,flags)
  47. int s;        /* Socket index */
  48. char *buf;    /* User buffer */
  49. int len;    /* Max length to receive */
  50. int flags;    /* Unused; will eventually select oob data, etc */
  51. {
  52.     struct mbuf *bp;
  53.     int cnt;
  54.  
  55.     if(len == 0)
  56.         return 0;    /* Otherwise would be interp as "all" */
  57.  
  58.     if((cnt = recv_mbuf(s,&bp,flags,NULLCHAR,0)) > 0) {
  59.         cnt = (int)min(cnt,len);
  60.         pullup(&bp,buf,(int16)cnt);
  61.         free_p(bp);
  62.     }
  63.     return cnt;
  64. }
  65. #endif
  66.  
  67. #ifdef XXX
  68. /* Higher level receive routine, intended for datagram sockets. Can also
  69.  * be used for connection-oriented sockets, although from and fromlen are
  70.  * ignored.
  71.  */
  72. int
  73. recvfrom(s,buf,len,flags,from,fromlen)
  74. int s;        /* Socket index */
  75. char *buf;    /* User buffer */
  76. int len;    /* Maximum length */
  77. int flags;    /* Unused; will eventually select oob data, etc */
  78. char *from;    /* Source address, only for datagrams */
  79. int *fromlen;    /* Length of source address */
  80. {
  81.     struct mbuf *bp;
  82.     int cnt;
  83.  
  84.     if((cnt = recv_mbuf(s,&bp,flags,from,fromlen)) > 0) {
  85.         cnt = (int)min(cnt,len);
  86.         pullup(&bp,buf,(int16)cnt);
  87.         free_p(bp);
  88.     }
  89.     return cnt;
  90. }
  91. #endif
  92.  
  93. /* High level send routine */
  94. int
  95. send(
  96. int s,        /* Socket index */
  97. char *buf,    /* User buffer */
  98. int len,    /* Length of buffer */
  99. int flags)    /* Unused; will eventually select oob data, etc */
  100. {
  101.     struct mbuf *bp;
  102.     char sock[MAXSOCKSIZE];
  103.     int i = MAXSOCKSIZE;
  104.  
  105.     if(getpeername(s,sock,&i) == EOF)
  106.         return EOF;
  107.     bp = qdata(buf,(int16)len);
  108.     return send_mbuf(s,bp,flags,sock,i);
  109. }
  110.  
  111. /* High level send routine, intended for datagram sockets. Can be used on
  112.  * connection-oriented sockets, but "to" and "tolen" are ignored.
  113.  */
  114. int
  115. sendto(
  116. int s,        /* Socket index */
  117. char *buf,    /* User buffer */
  118. int len,    /* Length of buffer */
  119. int flags,    /* Unused; will eventually select oob data, etc */
  120. char *to,    /* Destination, only for datagrams */
  121. int tolen)    /* Length of destination */
  122. {
  123.     struct mbuf *bp = qdata(buf,(int16)len);
  124.  
  125.     return send_mbuf(s,bp,flags,to,tolen);
  126. }
  127.  
  128. /* Receive a newline-terminated line from a socket, returning # chars read.
  129.  * The end-of-line sequence is recognized and translated into a single '\n'.
  130.  */
  131. int
  132. recvline(
  133. int s,            /* Socket index */
  134. char *buf,        /* User buffer */
  135. unsigned len)    /* Length of buffer */
  136. {
  137.     int c, cnt = 0;
  138.  
  139.     while(len-- > 1) {
  140.         if((c = recvchar(s)) == EOF){
  141.             cnt = EOF;
  142.             break;
  143.         }
  144.         if(buf != NULLCHAR) {
  145.             *buf++ = c;
  146.         }
  147.         cnt++;
  148.  
  149.         if(uchar(c) == '\n') {
  150.             break;
  151.         }
  152.     }
  153.     if(buf != NULLCHAR) {
  154.         *buf = '\0';
  155.     }
  156.     return cnt;
  157. }
  158.  
  159. #if    defined(ANSIPROTO)
  160. /* Do printf on a user socket */
  161. int
  162. usprintf(int s,char *fmt,...)
  163. {
  164.     va_list args;
  165.     int len;
  166.  
  167.     va_start(args,fmt);
  168.     len = usvprintf(s,fmt,args);
  169.     va_end(args);
  170.     return len;
  171. }
  172.  
  173. /* Printf on standard output socket */
  174. int
  175. tprintf(char *fmt,...)
  176. {
  177.     va_list args;
  178.     int len;
  179.  
  180.     va_start(args,fmt);
  181.     len = usvprintf(Curproc->output,fmt,args);
  182.     va_end(args);
  183.     return len;
  184. }
  185.  
  186. /* The guts of printf, uses variable arg version of sprintf */
  187. static int near
  188. usvprintf(int s,char *fmt,va_list args)
  189. {
  190.     int i, len;
  191.     char *cp;
  192.  
  193.     if(strchr(fmt,'%') == NULLCHAR) {
  194.         /* No args, so we don't need vsprintf() */
  195.         len = strlen(fmt);
  196.         cp = fmt;
  197.     } else {
  198.         char buf[SOBUF];
  199.         /* Use a default value that is hopefully longer than the
  200.          * biggest output string we'll ever print (!)
  201.          */
  202.         cp = buf;
  203.         vsprintf(cp,fmt,args);
  204.         len = strlen(cp);
  205.     }
  206.     i = len;
  207.  
  208.     while(i-- > 0) {
  209.         if(usputc(s,*cp++) == EOF) {
  210.             return EOF;
  211.         }
  212.     }
  213.     return len;
  214. }
  215. #else
  216. /*VARARGS*/
  217. /* Printf to standard output socket */
  218. int
  219. tprintf(fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
  220. char *fmt;        /* Message format */
  221. int arg1,arg2,arg3;    /* Arguments */
  222. int arg4,arg5,arg6;
  223. int arg7,arg8,arg9;
  224. int arg10,arg11,arg12;
  225. {
  226.     return usprintf(Curproc->output,fmt,arg1,arg2,arg3,arg4,arg5,arg6,
  227.         arg7,arg8,arg9,arg10,arg11,arg12);
  228. }
  229. /* Printf to socket. Doesn't use ANSI vsprintf */
  230. int
  231. usprintf(s,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
  232. int s;            /* Socket index */
  233. char *fmt;        /* Message format */
  234. int arg1,arg2,arg3;    /* Arguments */
  235. int arg4,arg5,arg6;
  236. int arg7,arg8,arg9;
  237. int arg10,arg11,arg12;
  238. {
  239.     int i, len;
  240.     char *cp;
  241.  
  242.     if(strchr(fmt,'%') == NULLCHAR){
  243.         /* No args, so we don't need vsprintf() */
  244.         char *buf1 = fmt;
  245.         len = strlen(buf1);
  246.         cp = buf1;
  247.     } else {
  248.         /* Use a default value that is hopefully longer than the
  249.          * biggest output string we'll ever print (!)
  250.          */
  251.         char buf[SOBUF];
  252.  
  253.         cp = buf;
  254.         sprintf(cp,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,
  255.             arg8,arg9,arg10,arg11,arg12);
  256.         len = strlen(cp);
  257.     }
  258.     i = len;
  259.  
  260.     while(i-- > 0) {
  261.         if(usputc(s,*cp++) == EOF) {
  262.             return EOF;
  263.         }
  264.     }
  265.     return len;
  266. }
  267. #endif
  268.  
  269. /* Buffered putchar to a socket */
  270. int
  271. usputc(int s,char c)
  272. {
  273.     struct mbuf *bp;
  274.     struct usock *up = itop(s);
  275.  
  276.     if(up == NULLUSOCK) {
  277.         return EOF;
  278.     }
  279.     if(up->obuf == NULLBUF) {
  280.         /* Allocate a buffer of appropriate size */
  281. #ifdef NETROM
  282.         switch(up->type){
  283.         case TYPE_NETROML4:
  284.             up->obuf = alloc_mbuf(Nr_iface->mtu);
  285.             break;
  286.         default:
  287.             up->obuf = alloc_mbuf(SOBUF);
  288.             break;
  289.         }
  290. #else
  291.         up->obuf = alloc_mbuf(SOBUF);
  292. #endif
  293.     }
  294.     bp = up->obuf;
  295.  
  296.     if(c == '\n' && (up->flag & SOCK_ASCII)) {
  297.         char *cp;
  298.         /* Translate into appropriate end-of-line sequence */
  299.         for(cp = up->eol; *cp != '\0'; cp++) {
  300. #ifdef LZW
  301.             if(up->zout == NULLLZW) {
  302.                 bp->data[bp->cnt++] = *cp;
  303.             } else {
  304.                 lzwencode(s,*cp);
  305.             }
  306. #else
  307.             bp->data[bp->cnt++] = *cp;
  308. #endif
  309.         }
  310.     } else {
  311. #ifdef LZW
  312.         if(up->zout == NULLLZW) {
  313.             bp->data[bp->cnt++] = c;
  314.         } else {
  315.             lzwencode(s,c);
  316.         }
  317. #else
  318.         bp->data[bp->cnt++] = c;
  319. #endif
  320.     }
  321.     /* Always leave enough room for an eol sequence in the next call */
  322.     if((c == up->flush && up->flush != EOF) || bp->cnt >= bp->size - 9) {
  323.         if(usflush(s) == EOF) {
  324.             return EOF;
  325.         }
  326.     }
  327.     return (int)uchar(c);
  328. }
  329.  
  330. int
  331. usputs(int s,char *x)
  332. {
  333.     int len = 0;
  334.  
  335.     while(*x != '\0') {
  336.         if(usputc(s,*x++) == EOF) {
  337.             return EOF;
  338.         }
  339.         len++;
  340.     }
  341.     return len;
  342. }
  343.  
  344. #ifdef XXX
  345. /* Put a character to standard output socket */
  346. int
  347. tputc(char c)
  348. {
  349.     return usputc(Curproc->output,c);
  350. }
  351. #endif
  352.  
  353. /* Put a string to standard output socket */
  354. int
  355. tputs(char *s)
  356. {
  357.     int len = 0;
  358.  
  359.     while(*s != '\0') {
  360.         if(usputc(Curproc->output,*s++) == EOF) {
  361.             return EOF;
  362.         }
  363.         len++;
  364.     }
  365.     return len;
  366. }
  367.  
  368. /* Read a raw character from a socket with stream buffering. */
  369. int
  370. rrecvchar(int s)        /* Socket index */
  371. {
  372.     struct usock *up;
  373.  
  374.     if((up = itop(s)) != NULLUSOCK) {
  375. #ifdef LZW
  376.         int c;
  377.  
  378.         if(up->zin != NULLLZW && (c = lzwdecode(up)) != EOF) {
  379.             return c;
  380.         }
  381.         /* Replenish if necessary */
  382.         if(up->ibuf == NULLBUF && recv_mbuf(s,&up->ibuf,0,NULLCHAR,0) <= 0) {
  383.             return EOF;
  384.         }
  385.         if(up->zin != NULLLZW) {
  386.             if((c = lzwdecode(up)) != EOF) {
  387.                 return c;
  388.             } else {
  389.                 return rrecvchar(s);    /* need to replenish */
  390.             }
  391.         }
  392. #else
  393.         /* Replenish if necessary */
  394.         if(up->ibuf == NULLBUF && recv_mbuf(s,&up->ibuf,0,NULLCHAR,0) <= 0) {
  395.             return EOF;
  396.         }
  397. #endif
  398.         return PULLCHAR(&up->ibuf);    /* Returns EOF if eof */
  399.     }
  400.     return EOF;
  401. }
  402.  
  403. /* This function recognizes the end-of-line sequence for the stream
  404.  * and translates it into a single '\n'.
  405.  */
  406. int
  407. recvchar(int s)            /* Socket index */
  408. {
  409.     struct usock *up;
  410.  
  411.     if((up = itop(s)) != NULLUSOCK) {
  412.         int c;
  413.  
  414.         if((c = rrecvchar(s)) != up->eol[0] || !(up->flag & SOCK_ASCII)) {
  415.             return c;
  416.         }
  417.         /* This is the first char of a eol sequence. If the eol sequence
  418.          * is more than one char long, eat the next character in the
  419.          * input stream.
  420.          */
  421.         if(up->eol[1] != '\0') {
  422.             rrecvchar(s);
  423.         }
  424.         return '\n';
  425.     }
  426.     return EOF;
  427. }
  428.  
  429. /* Flush output on a socket stream */
  430. int
  431. usflush(int s)
  432. {
  433.     struct usock *up = itop(s);
  434.  
  435.     if(up != NULLUSOCK) {
  436.         struct mbuf *bp = up->obuf;
  437.  
  438.         if(bp != NULLBUF) {
  439. #ifdef LZW
  440.             if(up->zout != NULLLZW) {
  441.                 lzwflush(up);
  442.             }
  443. #endif
  444.             up->obuf = NULLBUF;
  445.             return send_mbuf(s,bp,0,NULLCHAR,0);
  446.         }
  447.         return 0;
  448.     }
  449.     return EOF;
  450. }
  451.  
  452. /* Flush output socket */
  453. void
  454. tflush()
  455. {
  456.     usflush(Current->output);
  457. }
  458.  
  459. /* Print prompt and read one character */
  460. int
  461. keywait(
  462. char *prompt,    /* Optional prompt */
  463. int flush)        /* Flush queued input? */
  464. {
  465.     int c, i;
  466.  
  467.     if(flush && socklen(Curproc->input,1) != 0) {
  468.         recv_mbuf(Curproc->input,NULLBUFP,0,NULLCHAR,0); /* flush */
  469.     }
  470.     if(prompt == NULLCHAR) {
  471.         prompt = "Hit enter to continue";
  472.     }
  473.     tputs(prompt);
  474.     usflush(Curproc->output);
  475.  
  476.     c = recvchar(Curproc->input);
  477.  
  478.     /* Get rid of the prompt */
  479.     for(i = strlen(prompt); i != 0; i--) {
  480.         tputs("\b \b");
  481.     }
  482.     usflush(Curproc->output);
  483.     return c;
  484. }
  485.  
  486. /* Set the end-of-line sequence on a socket */
  487. int
  488. seteol(int s,char *seq)
  489. {
  490.     struct usock *up;
  491.  
  492.     if((up = itop(s)) != NULLUSOCK) {
  493.         if(seq != NULLCHAR) {
  494.             strncpy(up->eol,seq,sizeof(up->eol));
  495.         } else {
  496.             *up->eol = '\0';
  497.         }
  498.         return 0;
  499.     }
  500.     return EOF;
  501. }
  502.  
  503. /* Enable/disable eol translation, return previous state */
  504. int
  505. sockmode(int s,int mode)
  506. {
  507.     struct usock *up;
  508.  
  509.     if((up = itop(s)) != NULLUSOCK) {
  510.         int prev = up->flag;
  511.  
  512.         usflush(s);
  513.         switch(mode){
  514.         case SOCK_BINARY:
  515.         case SOCK_ASCII:
  516.             up->flag = mode;
  517.             break;
  518.         }
  519.         return prev;
  520.     }
  521.     return EOF;
  522. }
  523.  
  524. /* Specify the character to trigger automatic output buffer
  525.  * flushing, or EOF to disable it. Return the previous setting.
  526.  */
  527. int
  528. setflush(int s,int c)
  529. {
  530.     struct usock *up;
  531.  
  532.     usflush(s);
  533.  
  534.     if((up = itop(s)) != NULLUSOCK) {
  535.         int old = up->flush;
  536.         up->flush = c;
  537.         return old;
  538.     }
  539.     return EOF;
  540. }
  541.  
  542.